﻿//------------------------------------------------------------------------------
// ╭─────────────────────────────╮
// │ ╭─╮     ╭─╮              TM │   ╠═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╣
// │ │ │     │ │                 │                                           ☺  
// │ │ ╰───╮ │ │ ╭─────╮ ╭─────╮ │     Name:Wedn.Net 文章异步请求处理程序  ♮ ♪ ♩
// │ │ ╭─╮ │ │ │ │ ╭─╮ │ │ ╭─╮ │ │                                    ♫ ♭      
// │ │ ╰─╯ │ │ │ │ ╰─╯ │ │ ╰─╯ │ │     Author:iceStone               ♬ ♪       
// │ └─────╯ └─╯ ╰─────╯ ╰───╮ │ │     Chinese:汪磊                              
// │                     ┌───╯ │ │                                              
// │                     ╰─────╯ │   ╠═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╣
// ╰─────────────────────────────╯                                              
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using Wedn.Net.Common;
using Wedn.Net.IBLL;
using Wedn.Net.Model;
using Wedn.Net.UI.Handlers;
using Wedn.Net.Utility;

namespace Wedn.Net.Web.Handlers
{
    /// <summary>
    /// 文章异步请求处理程序
    /// </summary>
    public class PostAjax : AdminBaseHandler
    {
        private HttpContext _context;
        private readonly IBLLFactory _bllInstance = BLLFactory.BLLFactory.Instance;
        /// <summary>
        /// PR方法
        /// </summary>
        /// <param name="context"></param>
        public override void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            _context = context;
            string action = RequestHelper.QueryString("action");
            switch (action)
            {
                case "move_trash":
                    MoveToTrash();
                    break;
                case "move_normal":
                    MoveToNormal();
                    break;
                case "load_post":
                    LoadPost();
                    break;
                case "load_category_post":
                    LoadCategoryPost();
                    break;
                case "load_status_post":
                    LoadStatusPost();
                    break;
                case "get_marker":
                    GetMarker();
                    break;
                case "publish":
                    Publish(0);
                    break;
                case "edit":
                    Publish(RequestHelper.FormInt("post_id"));
                    break;
            }
        }

        /// <summary>
        /// 插入发表物
        /// </summary>
        private void Publish(int postId)
        {
            #region 处理发表物
            Post entity = null;
            if (postId == 0)
            {
                //新增文章
                entity = new Post();
                entity.UserId = RequestHelper.FormInt("post_author");
                entity.Slug = RequestHelper.FormString("post_slug").ToSlug();
                entity.Title = RequestHelper.FormString("post_title");
                entity.PubDate = RequestHelper.FormString("post_pubdate").ToDataTime(DateTime.Now);
                entity.Modified = RequestHelper.FormString("post_modified").ToDataTime(DateTime.Now);
                entity.Content = RequestHelper.FormString("post_content");
                entity.Excerpt = RequestHelper.FormString("post_excerpt");
                entity.Type = RequestHelper.FormString("post_type").ToShort();
                entity.IsTop = RequestHelper.FormString("post_istop").ToBoolean();
                entity.Status = RequestHelper.FormString("post_status").ToShort();
                entity.CommentStatus = RequestHelper.FormString("post_comment_status").ToShort();
                entity.PingStatus = RequestHelper.FormString("post_ping_status").ToShort();
                entity.Pinged = string.Empty;
                entity.Password = RequestHelper.FormString("post_password");
                _bllInstance.PostManager.Insert(entity);//向数据库上下文插入文章实体
            }
            else
            {
                //修改文章
                entity = _bllInstance.PostManager.SelectSingle(p => p.Id == postId);
                entity.UserId = RequestHelper.FormInt("post_author");
                entity.Slug = RequestHelper.FormString("post_slug").ToSlug();
                entity.Title = RequestHelper.FormString("post_title");
                entity.Modified = RequestHelper.FormString("post_modified").ToDataTime(DateTime.Now);
                entity.Content = RequestHelper.FormString("post_content");
                entity.Excerpt = RequestHelper.FormString("post_excerpt");
                entity.Type = RequestHelper.FormString("post_type").ToShort();
                entity.IsTop = RequestHelper.FormString("post_istop").ToBoolean();
                entity.Status = RequestHelper.FormString("post_status").ToShort();
                entity.CommentStatus = RequestHelper.FormString("post_comment_status").ToShort();
                entity.PingStatus = RequestHelper.FormString("post_ping_status").ToShort();
                entity.Pinged = string.Empty;
                entity.Password = RequestHelper.FormString("post_password");
                _bllInstance.PostManager.Update(entity);
            }
            int rows = _bllInstance.DbSaveChanges();//同步数据库上下文变化到数据库 
            #endregion

            //创建关系对象集合
            var relations = new List<Relation>();
            var terms = _bllInstance.TermManager.Select(t => true).ToList();

            #region 处理标签
            string tag = RequestHelper.FormString("post_tag");
            if (!string.IsNullOrEmpty(tag))
            {
                string[] tags = tag.Split(new[] { ',', '|', '，' }, StringSplitOptions.RemoveEmptyEntries);
                //获取已存在的标签数据
                IList<Term> existTags = terms.Where(t => t.Type == (int)TermType.PostTag && tags.Contains(t.Name)).ToList();
                IList<int> tagIds = new List<int>();//existTags.Select(t => t.Id).ToList();
                IList<string> existTagsName = new List<string>(); //existTags.Select(t => t.Name).ToArray();
                //更新标签文章数量
                foreach (var t in existTags)
                {
                    t.Count++;
                    tagIds.Add(t.Id);
                    existTagsName.Add(t.Name);
                    _bllInstance.TermManager.Update(t);//更新文章数
                }
                //创建新标签集合
                IList<Term> newTags = tags.Where(t => !existTagsName.Contains(t))
                                          .Select(t => new Term { Name = t, Description = string.Empty, ParentId = -1, Slug = string.Empty, Count = 1 })
                                          .ToList();
                _bllInstance.TermManager.Insert(newTags.ToArray());//向数据库上下文插入标签实体
                rows += _bllInstance.DbSaveChanges();//同步数据库上下文变化到数据库
                foreach (var t in newTags)
                {
                    tagIds.Add(t.Id);
                }
                relations.AddRange(tagIds.Select(i => new Relation { ObjectId = entity.Id, ObjectType = (int)RelationObjectType.Post, TermId = i }).ToList());
            }
            #endregion

            #region 处理分类关系
            string category = RequestHelper.FormString("post_category");
            if (!string.IsNullOrEmpty(category))
            {
                int[] categoryIds = category.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                           .Select(i => i.ToInt(0))
                                           .Where(i => i != 0)
                                           .ToArray();
                relations.AddRange(categoryIds.Select(i => new Relation { ObjectId = entity.Id, ObjectType = (int)RelationObjectType.Post, TermId = i }).ToList());
                var categorys = _bllInstance.TermManager.Select(c => categoryIds.Contains(c.Id));
                foreach (var cat in categorys)
                {
                    cat.Count++;
                    _bllInstance.TermManager.Update(cat);//更新文章数
                }
            }
            else
            {
                var cat = _bllInstance.TermManager.SelectSingle(c => c.Id == 1);
                cat.Count++;
                _bllInstance.TermManager.Update(cat);
                relations.Add(new Relation { ObjectId = entity.Id, ObjectType = (int)RelationObjectType.Post, TermId = 1 });
            }
            #endregion

            //保存关系
            if (relations.Count > 0)
            {
                var delRel = _bllInstance.RelationManager.Select(r => r.ObjectId == postId && r.ObjectType == (int)RelationObjectType.Post);
                foreach (var rel in delRel)
                {
                    Term term = terms.FirstOrDefault(t => t.Id == rel.TermId);
                    term.Count--;
                    _bllInstance.TermManager.Update(term);
                    _bllInstance.RelationManager.Delete(rel);
                }
                foreach (var rel in relations)
                    _bllInstance.RelationManager.Insert(rel);//向数据库上下文插入关系实体
                rows += _bllInstance.DbSaveChanges();//同步数据库上下文变化到数据库 
            }
            ResponseStr(rows > 0 ? string.Format("{{\"Status\":0,\"PostId\":{0},\"PostLink\":\"{1}post/{2}\"}}", entity.Id, Config.SiteUrl, entity.Slug) : string.Format("{{\"Status\":1,\"Message\":\"发表失败，请稍后重试\"}}"));
        }

        /// <summary>
        /// 获取地区标签
        /// </summary>
        private void GetMarker()
        {
            var wc = new WebClient { Encoding = Encoding.UTF8 };
            string res = wc.DownloadString("http://api.map.baidu.com/location/ip?ak=BDb449eafd7aacbfff666c48f08ce364&ip=" + RequestHelper.IPAddress);
            ResponseStr(res);
        }

        /// <summary>
        /// 加载状态下数据
        /// </summary>
        private void LoadStatusPost()
        {
            int catId = RequestHelper.QueryInt("cat");
            string status = RequestHelper.QueryString("status");
            if (status == "all")
                LoadData(1, 30, catId, null);
            else
                LoadData(1, 30, catId, (PostStatus)StringHelper.StrToInt(status));
        }

        /// <summary>
        /// 加载类别下数据
        /// </summary>
        private void LoadCategoryPost()
        {
            int catId = RequestHelper.QueryInt("cat");
            int status = RequestHelper.QueryInt("status");
            LoadData(1, 30, catId, (PostStatus)status);
        }

        /// <summary>
        /// 分页加载数据
        /// </summary>
        private void LoadPost()
        {
            int pageIndex = RequestHelper.QueryInt("page");
            int pageSize = RequestHelper.QueryInt("size");
            int catId = RequestHelper.QueryInt("cat");
            int status = RequestHelper.QueryInt("status");
            LoadData(pageIndex, pageSize, catId, (PostStatus)status);
        }

        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="catId">类别Id</param>
        /// <param name="status">Post状态</param>
        private void LoadData(int pageIndex, int pageSize, int catId, PostStatus? status)
        {
            int totalCount;
            var terms = _bllInstance.TermManager.Select(t => true).ToList();
            var relations = _bllInstance.RelationManager.Select(r => r.ObjectType == (int)RelationObjectType.Post).ToList();
            IList<Post> list;
            if (catId != -1)
            {
                int[] categoryIds = _bllInstance.TermManager.GetSubCategorys(terms.Where(c => c.Type == (int)TermType.PostCategory).ToList(), catId).Select(c => c.Id).ToArray();
                var postIds = relations.Where(r => categoryIds.Contains(r.TermId)).Select(r => r.ObjectId);
                if (status == null)
                {
                    list = _bllInstance.PostManager.SelectPage(pageIndex, pageSize, out totalCount,
                     p =>
                     postIds.Contains(p.Id) &&
                     p.Type == (int)PostType.Article,
                     p => p.Modified, true
                     ).ToList();
                }
                else
                {
                    list = _bllInstance.PostManager.SelectPage(pageIndex, pageSize, out totalCount,
                     p =>
                     postIds.Contains(p.Id) &&
                     p.Type == (int)PostType.Article &&
                     p.Status == (int)status,
                     p => p.Modified, true
                     ).ToList();
                }
            }
            else
            {
                if (status == null)
                {
                    list = _bllInstance.PostManager.SelectPage(pageIndex, pageSize, out totalCount,
                    p =>
                    p.Type == (int)PostType.Article,
                    p => p.Modified, true
                    ).ToList();
                }
                else
                {

                    list = _bllInstance.PostManager.SelectPage(pageIndex, pageSize, out totalCount,
                    p =>
                    p.Type == (int)PostType.Article &&
                    p.Status == (int)status,
                    p => p.Modified, true
                    ).ToList();
                }
            }
            var viewList = (from item in list
                            let ids = relations.Where(r => r.ObjectId == item.Id).Select(r => r.TermId)
                            let thisTerms = terms.Where(c => ids.Contains(c.Id))
                            select new Model.View.Post
                                {
                                    Id = item.Id,
                                    Title = item.Title,
                                    Author = item.UserId.ToString(),
                                    Category = string.Join("、", thisTerms.Where(c => c.Type == (int)TermType.PostCategory).Select(c => string.Format("<a href=\"/category/{0}\" target=\"_blank\">{1}</a>", c.Slug, c.Name))),
                                    Tag = string.Join("、", thisTerms.Where(c => c.Type == (int)TermType.PostTag).Select(c => string.Format("<a href=\"/tag/{0}\" target=\"_blank\">{1}</a>", c.Slug, c.Name))),
                                    CommentCount = item.CommentCount,
                                    Date = StringHelper.DateTimeToChsStr(item.Modified)
                                }).ToList();
            var jsSerializer = new JavaScriptSerializer();
            ResponseStr(jsSerializer.Serialize(new { TotalCount = totalCount, List = viewList }));
        }

        /// <summary>
        /// 修改状态正常
        /// </summary>
        private void MoveToNormal()
        {
            string temp = RequestHelper.QueryString("ids");
            if (!string.IsNullOrEmpty(temp))
            {
                var intIds = temp.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(i => i.ToInt());
                var postList = _bllInstance.PostManager.Select(p => intIds.Contains(p.Id)).ToList();
                foreach (var post in postList.Where(p => p.UserId != CurrentUser.Id))
                    _context.Response.End();//越权
                //int res = 0;
                foreach (var item in postList)
                {
                    item.Status = (int)PostStatus.Default;
                    _bllInstance.PostManager.Update(item);
                }
                int res = _bllInstance.DbSaveChanges();
                ResponseStr(res == intIds.Count() ? "success" : "error");
            }
        }

        /// <summary>
        /// 修改状态回收站
        /// </summary>
        private void MoveToTrash()
        {
            string temp = RequestHelper.QueryString("ids");
            if (!string.IsNullOrEmpty(temp))
            {
                var intIds = temp.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(i => i.ToInt());
                var postList = _bllInstance.PostManager.Select(p => intIds.Contains(p.Id)).ToList();
                foreach (var post in postList.Where(p => p.UserId != CurrentUser.Id))
                    _context.Response.End();//越权
                foreach (var item in postList)
                {
                    item.Status = (int)PostStatus.Recycle;
                    _bllInstance.PostManager.Update(item);
                }
                int res = _bllInstance.DbSaveChanges();
                ResponseStr(res == intIds.Count() ? "success" : "error"); 
            }
        }
    }
}